// File UserInterface.cpp
//
// Purpose: Provides functions for user interface
//
// Author : Bryson King
// Date : 20 March 2013
// --------------------------------------------------------------

#include "UserInterface.h"

#include <algorithm>	// complex string operations
#include <iostream>
#include <string>

#include "CombatInterface.h"
#include "misc/ConsoleUtils.h"
#include "IPerson.h"
#include "InterfaceStructures.h"
#include "Item.h"
#include "Player.h"
#include "AbstractLocation.h"

using namespace std;

bool CUserInterface::UserRequestsQuitGame = false;
bool CUserInterface::GameOver = false;
bool CUserInterface::InCombat = false;
bool CUserInterface::UserDied = false;
bool CUserInterface::StopAfterEachRound = false;
CCombatInterface* CUserInterface::m_cCombatInterface = nullptr;

void CUserInterface::ClearScreen()
{
	SetTextColor(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);
	for (int i=0; i<25; i++)
		cout << endl;
}

void CUserInterface::StartUserInterface()
{
	// Intro Text
	SetTextColor(BACKGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
	ClearScreen();
	cout << "Welcome to the USS Enterprise." << endl;
	cout << "You have ... blah, blah, blah." << endl;
		
	// Set user quit flag to false
}

void CUserInterface::EndUserInterface()
{
	// Outcome text
	ClearScreen();
	cout << endl << endl;
	SetTextColor(BACKGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);
	// Display appropriate message to user about status of end game
	if (UserDied)
	{
		cout << "You were killed! Game Over!";
	} else if (UserRequestsQuitGame) {
		cout << "You have lost due to giving up. You are a LOSER!";
	} else if (GameOver) {
		cout << "You have lost due to the terrorist's being better people than you!";
	} else {
		cout << "You lost due to some unknown glitch!";
	}

	// Wait for a keypress before exiting
	SetTextColor(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);
	cout << endl;
	PressAnyKeyToContinue();
}

string CUserInterface::UserSelectionPrompt(user_input_options user_options, CLocation* pLocationOfPlayer, IPerson* &pEnemy)
{
	
	string sUserInput;

	SetTextColor(FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);

	cout << endl << endl << "You are currently located in " << 
		user_options.location_name << "." << endl;

	SetTextColor(FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY);

	// Display the different people in the location
	if (pLocationOfPlayer->NumberOfPeopleAtLocation() > 1)
	{
		cout << endl << "There are currently the following people here: ";
	}
	bool bPreviousOption = false;	// used to determine if need separating pipeline
	for (int i = 0; i < pLocationOfPlayer->NumberOfPeopleAtLocation(); i++)
	{
		if (pLocationOfPlayer->RetrieveEntity(i)->Name() != GetNameOfEntity(ent_Player))
		{
			if (bPreviousOption)
				cout << " | ";
			cout << pLocationOfPlayer->RetrieveEntity(i)->Name();
			bPreviousOption = true;
		}
	}

	// Display the different locations available
	cout << endl << "You may go: ";

	// Output the directions the player can move
	bPreviousOption = false;	// used to determine if need separating pipeline
	for each (string s in user_options.locations_available)
	{
		if (s != "")
		{
			if (bPreviousOption)
				cout << " | ";
			cout << s;
			bPreviousOption = true;
		}
	}

	// If there are items available, display them
	int iNumberOfItems;
	SItem** pItemList = pLocationOfPlayer->RetrieveItemsAtLocation()->RetrieveAllItems(iNumberOfItems);
	if (iNumberOfItems > 0)
	{
		cout << endl << "The following items are available to take: ";
		bPreviousOption = false;
		for (int i = 0; i < iNumberOfItems; i++)
		{
			if (bPreviousOption)
				cout << " | ";
			cout << pItemList[i]->Name;
			bPreviousOption = true;
		}
	}

	// If there are other options available, output them as well
	cout << endl << "You may also choose to: ";
	for each (string s in user_options.other_options_available)
	{
		if (s != "")
			cout << s << " | ";
	}
	// Allow player to attack entity if there is one in the location
	for (int i = 0; i < pLocationOfPlayer->NumberOfPeopleAtLocation(); i++)
	{
		if ((pLocationOfPlayer->RetrieveEntity(i)->Name() != GetNameOfEntity(ent_Player)) &&
			(pLocationOfPlayer->RetrieveEntity(i)->PersonAlive()))
			cout << "ATTACK " << pLocationOfPlayer->RetrieveEntity(i)->Name() << " | ";
	}
	// Allow searching of all dead people in the area
	for (int i = 0; i < pLocationOfPlayer->NumberOfPeopleAtLocation(); i++)
	{
		if (!pLocationOfPlayer->RetrieveEntity(i)->PersonAlive())
			cout << "SEARCH " << pLocationOfPlayer->RetrieveEntity(i)->Name() << " | ";
	}
	// Always provide the option for the player to check their inventory
	cout << "INVENTORY" << " | ";
	// Always provide the option for the player to quit the game as well
	cout << "QUIT GAME";

	// Request input from the user
	cout << endl << "What would you like to do? ";
	getline(std::cin, sUserInput);
	transform(sUserInput.begin(), sUserInput.end(), sUserInput.begin(), toupper);

	CUserInterface::ClearScreen();

	// Determine the input of the user and return that value
	for each (string s in user_options.locations_available)
	{
		if (s == sUserInput)
			return s;
	}
	for (int i = 0; i < iNumberOfItems; i++)
	{
		if (("TAKE " + pItemList[i]->Name) == sUserInput)
		{
			cout << "You have picked up the " << pItemList[i]->Name << "." << endl;
			return pItemList[i]->Name;
		}
	}
	for each (string s in user_options.other_options_available)
	{
		if (s == sUserInput)
			return s;
	}
	string sNameOfEntity;
	for (int i = 0; i < pLocationOfPlayer->NumberOfPeopleAtLocation(); i++)
	{
		sNameOfEntity = pLocationOfPlayer->RetrieveEntity(i)->Name();
		transform(sNameOfEntity.begin(), sNameOfEntity.end(), sNameOfEntity.begin(), toupper);		
		if (("ATTACK " + sNameOfEntity) == sUserInput)
		{
			pEnemy = pLocationOfPlayer->RetrieveEntity(i);
			return "ATTACK";
		}
	}
	for (int i = 0; i < pLocationOfPlayer->NumberOfPeopleAtLocation(); i++)
	{
		sNameOfEntity = pLocationOfPlayer->RetrieveEntity(i)->Name();
		transform(sNameOfEntity.begin(), sNameOfEntity.end(), sNameOfEntity.begin(), toupper);		
		if (("SEARCH " + sNameOfEntity) == sUserInput)
		{
			pEnemy = pLocationOfPlayer->RetrieveEntity(i);

			return "SEARCH";
		}
	}
	if (sUserInput == "INVENTORY") {
		return sUserInput;
	} else if (sUserInput == "QUIT GAME") {
		UserRequestsQuitGame = true;
		return sUserInput;
	}

	// The option entered by the user was not understood; Recursively go through function
	//	until a valid option is entered by the user.
	SetTextColor(BACKGROUND_RED|BACKGROUND_INTENSITY|FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN);
	cout << endl << "The text you entered was not understood. Please try again." << endl;
	return UserSelectionPrompt(user_options, pLocationOfPlayer, pEnemy);
}

void CUserInterface::SearchEntity(IPerson* pPlayer, IPerson* &pEntity)
{
	SItem** pReturnItems = nullptr;
	int iCount;
	string sUserInput;
	bool bItemFound = false;

	ClearScreen();
	SetTextColor(BACKGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY);

	// Output header
	cout << "The following items are available on the dead body of " << pEntity->Name() << endl;
	cout << endl;

	// Display the list of items that were on the body of the entity to be searched
	pReturnItems = pEntity->RetrieveAllItemsFromInventory(iCount);
	for (int i = 0; i < iCount; i++)
	{
		cout << (i + 1) << ". " << pReturnItems[i]->Name;
		if (pReturnItems[i]->ProjectileWeapon)
			cout << endl << "     " << "Ammo in weapon: " << pReturnItems[i]->AmmoInWeapon;
		cout << endl;
	}

	// If no items on the entity
	if (iCount == 0)
		cout << "There are no items on the dead body." << endl;

	// Allow user to enter item wanted until user types 'X'
	cout << endl << "Enter the item you would like to pick up <X to exit>: ";
	getline(std::cin, sUserInput);
	transform(sUserInput.begin(), sUserInput.end(), sUserInput.begin(), toupper);
	while (sUserInput != "X")
	{
		// Get the item the user requested, add to User inventory, remove from Entity inventory
		for (int i = 0; i < iCount; i++)
		{
			if (pReturnItems[i]->Name == sUserInput)
			{
				pPlayer->AddItemToInventory(pReturnItems[i]);
				pEntity->RemoveFromInventory(pReturnItems[i]);
				bItemFound = true;
			}
		}

		// Check to see if the item was found and act appropriately
		if (bItemFound)
			cout << "The item was added to your inventory." << endl;
		else
			cout << "The item requested was not found. Please try again." << endl;

		// Reset for the next loop iteration
		bItemFound = false;

		getline(std::cin, sUserInput);
		transform(sUserInput.begin(), sUserInput.end(), sUserInput.begin(), toupper);
	}
}

void CUserInterface::CombatInterface(IPerson* pPlayer, IPerson* pEnemy, bool bUserInvolved)
{
	string sUserInput; 

	// If combat has not begun yet
	if (!InCombat)
	{
		// Call the combat interface class
		m_cCombatInterface = new CCombatInterface();
		if (bUserInvolved)
			m_cCombatInterface->StartCombatWithPlayer(pPlayer, pEnemy);
		else
			m_cCombatInterface->StartCombat(pPlayer, pEnemy);
		InCombat = true;
	} else {// If combat is already in progress
		// If combat is complete, remove the combat interface
		if (m_cCombatInterface->CombatCompleted())
		{
			delete m_cCombatInterface;
			m_cCombatInterface = nullptr;
			InCombat = false;
		} else {// Continue combat
			// Allow the user to select whether to continue the fight
			
			if (StopAfterEachRound) {
				SetTextColor(FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);

				while ((sUserInput != "CONTINUE") && (sUserInput != "RUN"))
				{
					cout << endl << "Would you like to CONTINUE the fight or RUN away like a coward? ";
					cin >> sUserInput;
					cout << endl;

					transform(sUserInput.begin(), sUserInput.end(), sUserInput.begin(), toupper);
		
					if ((sUserInput != "CONTINUE") && (sUserInput != "RUN"))
						cout << endl << "The input you entered was not understood. Please try again." << endl;
				}
				// Utilize the user input to set up the necessary actions
				if (sUserInput == "RUN") {
					delete m_cCombatInterface;
					m_cCombatInterface = nullptr;
					InCombat = false;
				} else if (sUserInput == "CONTINUE") {
					m_cCombatInterface->PerformCombatRound();
				} else {
					cout << "There was an issue with this portion of the code. Please investigate.";
				}
			} else {
				m_cCombatInterface->PerformCombatRound();
			}
		}
	}
}
